/**
 **************************************************************************
 * @file     main.c
 * @brief    main program
 **************************************************************************
 * OLED Demo 基于硬件IIC DMA 模式
 *
 **************************************************************************
 *
 */
#include "main.h"
#include "at32f413_clock.h"
#include "state_led.h"
#include "ssd1306.h"
#include "i2c_application.h"
#include "xtp_delay.h"
#include "use_printf.h"

using namespace OLED;
/* 全局变量 */
uint32_t systick_count = 0;
float tmp = 0.00f;

i2c_handle_type hi2cx;

const u8 ssd1306_address_1 = 0x78;

// 创建一个 SSD1306 类
// OLED 硬件连接信息
// iic -> I2C2
// SCL -> PB10
// SDA -> PB11
SSD1306 ssd1306{
    CRM_I2C2_PERIPH_CLOCK,
    CRM_GPIOB_PERIPH_CLOCK,
    CRM_GPIOB_PERIPH_CLOCK,
    I2C2,
    ssd1306_address_1,
    &hi2cx,
    GPIOB,
    GPIOB,
    GPIO_PINS_10,
    GPIO_PINS_11
};

LED state_led {GPIOA, GPIO_PINS_0, CRM_GPIOA_PERIPH_CLOCK};
Usart usart1;

int num1 = 123456789;
int num2 = -123456789;
float f1 = 0.0;
double d1 = 3.1415926;
int test_num;

/**
 * @brief  main function.
 * @param  none
 * @retval none
 */
int main(void)
{
    /* config nvic priority group */
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

    system_clock_config();
    
    SysTick_Config(SystemCoreClock / 1000);
	
    state_led.init();
    ssd1306.init(); // 初始化 ssd1306

    usart1.init();

	ssd1306.writeString("Hello,World!", Font_7x10);
    ssd1306.setCursor(10, 16);
	ssd1306.writeString("xiaotupo.com", Font_7x10);
	ssd1306.update();
    ssd1306.setCursor(0, 32);
    ssd1306.writeChinese(24, 0);
	ssd1306.writeChinese(24, 1);
	ssd1306.writeChinese(24, 2);
	ssd1306.writeChinese(24, 3);
    ssd1306.update();
    ssd1306.clear();
    
    while (1)
    {
		static int i=0;
        static float f = 0.0;
        ssd1306.setCursor(0,0);
        ssd1306.writeNumber(i, Font_7x10);
        ssd1306.setCursor(0, 16);
        ssd1306.writeFloat(f, Font_7x10);
        ssd1306.update();
		i++;
        f+=0.125f;
        delay_ms(100);
    }
}

/**
 * @brief  initializes peripherals used by the i2c.
 * @param  none
 * @retval none
 */
extern "C" void i2c_lowlevel_init(i2c_handle_type *hi2c)
{
    gpio_init_type gpio_initstructure;

    if (hi2c->i2cx == ssd1306.getIICx())
    {
        /* i2c periph clock enable */
        crm_periph_clock_enable(ssd1306.getI2CPeriphClock(), TRUE);
        crm_periph_clock_enable(ssd1306.getClkPeriphClock(), TRUE);
        crm_periph_clock_enable(ssd1306.getSdaPeriphClock(), TRUE);

        /* gpio configuration */
        gpio_initstructure.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
        gpio_initstructure.gpio_pull = GPIO_PULL_UP;
        gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
        gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;

        /* configure i2c pins: scl */
        gpio_initstructure.gpio_pins = ssd1306.getClkPin();
        gpio_init(ssd1306.getClkPort(), &gpio_initstructure);

        /* configure i2c pins: sda */
        gpio_initstructure.gpio_pins = ssd1306.getSdaPin();
        gpio_init(ssd1306.getSdaPort(), &gpio_initstructure);

        /* configure and enable i2c dma channel interrupt */
        nvic_irq_enable(I2Cx_DMA_TX_IRQn, 0, 0);

        nvic_irq_enable(I2C2_EVT_IRQn, 0, 0);
        nvic_irq_enable(I2C2_ERR_IRQn, 0, 0);

        crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);

        dma_reset(hi2c->dma_tx_channel);

        hi2c->dma_tx_channel = DMA1_CHANNEL4;

        dma_default_para_init(&hi2c->dma_init_struct);
        hi2c->dma_init_struct.peripheral_inc_enable = FALSE;
        hi2c->dma_init_struct.memory_inc_enable = TRUE;
        hi2c->dma_init_struct.peripheral_data_width =
            DMA_PERIPHERAL_DATA_WIDTH_BYTE;
        hi2c->dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
        hi2c->dma_init_struct.loop_mode_enable = FALSE;
        hi2c->dma_init_struct.priority = DMA_PRIORITY_LOW;
        hi2c->dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;

        dma_init(hi2c->dma_tx_channel, &hi2c->dma_init_struct);

        i2c_init(hi2c->i2cx, I2C_FSMODE_DUTY_2_1, ssd1306.getI2CSpeed());
        i2c_own_address1_set(hi2c->i2cx, I2C_ADDRESS_MODE_7BIT, ssd1306.getAddress());
    }
}
